
\chapter{Pattern}
\label{sec:appendix-pattern}
We reproduce here an example of a pattern.

%\lstset{prebreak=\raisebox{0ex}[0ex][0ex]
%        {\ensuremath{\rhookswarrow}}}
%\lstset{postbreak=\raisebox{0ex}[0ex][0ex]
%        {\ensuremath{\rcurvearrowse\space}}}
%\lstset{breaklines=true, breakatwhitespace=true}
%\lstset{numbers=left, numberstyle=\scriptsize}

\begin{lstlisting}[captionpos=b, caption={Pattern matching queries like
``Revenue per state in 2001?''}, label=lst:sparql, basicstyle=\small,
   numbers=left,
   breaklines=true,
   breakatwhitespace=true,
   numberstyle=\scriptsize]
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX data-binding: <http://viceversatech.com/rdfbeans/2.0/>
PREFIX bquery-model: <http://research.sap.corp/pattern/>
PREFIX grepo: <urn:grepo#>
PREFIX query-tree: <urn:grepo/query-tree#>
PREFIX slayer: <urn:grepo/slayer#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

CONSTRUCT {	
bquery-model:bquery data-binding:bindingClass
"com.sap.research.questionanswering.pattern.model.BusinessQuery" .
bquery-model:dimensionProjectionItem data-binding:bindingClass
"com.sap.research.questionanswering.pattern.model.DimensionProjectionItem" .
bquery-model:projectionItem data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.ExpressionProjectionItem" .
bquery-model:measureReference data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.MeasureReference" .
bquery-model:measure data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.Measure" .
bquery-model:memberClass data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.Dimension" .
bquery-model:memberFilter data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.MemberFilter" .
bquery-model:vectorMemberset data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.VectorMemberSet" .
bquery-model:member data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.Member" .
bquery-model:expressionProjectionItem data-binding:bindingClass "com.sap.research.questionanswering.pattern.model.ExpressionProjectionItem" .
_:bquery rdf:type <http://research.sap.corp/pattern/bquery> .
_:bquery bquery-model:bquery/analysisType "comparison" .	
_:bquery bquery-model:bquery/dataSource ?universeName .	
_:bquery bquery-model:bquery/hasProjectionItem _:dimensionProjectionItem_1 .
_:bquery bquery-model:bquery/hasProjectionItem _:measureProjectionItem_1 .	
?pattern <urn:grepo/pattern#matches> _:query .
?pattern rdfs:label ?patternLabel .
?pattern rdf:type ?patternType .
_:query rdf:type <urn:grepo/pattern#Query> .
_:query <urn:grepo/pattern#hasBusinessQuery> _:bquery .
_:bquery bquery-model:bquery/hasFilterClause _:memberFilterClause .
_:memberFilterClause rdf:type bquery-model:memberFilter .
_:memberFilterClause bquery-model:memberFilter/hasMemberSet _:memberSet .
_:memberSet rdf:type bquery-model:vectorMemberset .
_:memberSet bquery-model:typedMemberset/hasMemberClass _:memberDimension .
_:memberSet bquery-model:vectorMemberset/hasMember _:member_1 .
_:dimensionProjectionItem_1 rdf:type bquery-model:dimensionProjectionItem .
_:dimensionProjectionItem_1 bquery-model:dimension _:dimension_1 .
_:measureProjectionItem_1 rdf:type bquery-model:expressionProjectionItem .
_:measureProjectionItem_1 bquery-model:expressionProjectionItem/hasExpression _:measureExpression .	
_:measureExpression rdf:type bquery-model:measureReference .
_:measureExpression bquery-model:measureReference/hasMeasure _:measure_1 .
_:measure_1 rdf:type bquery-model:measure .
_:measure_1 rdfs:label ?measureLabel_1 .
_:measure_1 bquery-model:measure/hasMeasureId ?measureOriginUri_1 .
_:measure_1 rdfs:isDefinedBy ?measureUri_1 .
_:dimension_1 rdf:type bquery-model:memberClass .
_:dimension_1 rdfs:label ?dimensionLabel_1 .
_:dimension_1 bquery-model:memberClass/hasDimensionId ?dimensionOriginUri_1  .
_:dimension_1 rdfs:isDefinedBy ?dimensionUri_1 .
_:member_1 rdf:type <http://research.sap.corp/pattern/member> .
_:member_1 rdfs:label ?memberLabel .
_:member_1 bquery-model:member/hasValue ?memberLabel .
_:memberDimension rdf:type <http://research.sap.corp/pattern/memberClass> .
_:memberDimension rdfs:label ?memberDimensionLabel .
_:memberDimension bquery-model:memberClass/hasDimensionId ?memberOriginUri_1  .
_:memberDimension rdfs:isDefinedBy ?memberUri_1 .	
_:bquery <http://research.sap.corp/pattern#referencesEntity> _:measure_1 .
_:bquery <http://research.sap.corp/pattern#referencesEntity> _:dimension_1 .
_:bquery <http://research.sap.corp/pattern#referencesEntity> _:memberDimension .
_:bquery bquery-model:bquery/hasConfidence ?confidence .
}

WHERE {
?pattern rdfs:label ?patternLabel .
?pattern rdf:type ?patternType .
?queryUri query-tree:hasAnnotation ?annotationUri_1 .
?annotationUri_1 query-tree:hasAnnotationType <urn:grepo/features/instances#MeasureAnnotationType> .
?annotationUri_1 query-tree:referencesResource ?measureUri_1 .
?annotationUri_1 query-tree:confidence ?measureConfidence_1 .
?measureUri_1 rdfs:label ?measureLabel_1.
?measureUri_1 grepo:originUri ?measureOriginUri_1 .
?queryUri query-tree:hasAnnotation ?annotationUri_2 .
?annotationUri_2 query-tree:hasAnnotationType <urn:grepo/features/instances#DimensionAnnotationType>.
?annotationUri_2 query-tree:referencesResource ?dimensionUri_1.
?annotationUri_2 query-tree:confidence ?dimensionConfidence_1 .
?dimensionUri_1 rdfs:label ?dimensionLabel_1 .
?dimensionUri_1 grepo:originUri ?dimensionOriginUri_1 .  
?queryUri query-tree:hasAnnotation ?annotationUri_3 .
?annotationUri_3 query-tree:hasAnnotationType <urn:grepo/features/instances#DimensionValueAnnotationType> .
?annotationUri_3 query-tree:referencesResource ?memberUri_1 .
?annotationUri_3 rdfs:label ?memberLabel .
?annotationUri_3 query-tree:confidence ?memberConfidence_1 .
?memberUri_1 rdfs:label ?memberDimensionLabel .
?memberUri_1 grepo:originUri ?memberOriginUri_1 . 
?measureUri_1 slayer:hasUniverse ?universeId .
?dimensionUri_1 slayer:hasUniverse ?universeId .
?memberUri_1 slayer:hasUniverse ?universeId .
?universeId rdfs:label ?universeName .
?universeId slayer:hasLanguage ?language .	
LET (?confidence := ?measureConfidence_1 + ?dimensionConfidence_1 + ?memberConfidence_1 + 4)
}	
\end{lstlisting}

\chapter{Query logs}
\label{sec:appendix-query-logs}
In this appendix, we reproduce a short example of query logs captured by our
\ac{QA} framework. 
\begin{lstlisting}[captionpos=b, caption=Query log example,
label=lst:query-log, basicstyle=\small,
   numbers=left,
   breaklines=true,
   breakatwhitespace=true,
   numberstyle=\scriptsize]
{
 "userQuery":"revenue per city",
 "clickedDaslResultQuery":"NonEmpty((Revenue) IN City::(Revenue.DESC));",
 "PatternName":"1Measure_1Dimension_2Filters",
 "Universe":"S360_CLUB_EN",
 "Dimension":"City",
 "Measure":"Revenue",
 "resultType":"daslResult",
 "currentRank":"1.34",
 "resultopenTime":"1341495982562",
 "resultcloseTime":"1341496006179"
}
{
 "userQuery":"revenue per city",
 "clickedDaslResultQuery":"NonEmpty((Revenue) IN Resort::(Revenue.DESC));",
 "PatternName":"1Measure_1Dimension_2Filters",
 "Universe":"S360_CLUB_EN",
 "Dimension":"Resort",
 "Measure":"Revenue",
 "resultType":"daslResult",
 "currentRank":"0.81",
 "resultopenTime":"1341496007538",
 "resultcloseTime":"1341496009286"
} 
{
 "userQuery":"revenue per city",
 "clickedDaslResultQuery":"NonEmpty(([Sales revenue]) IN State::([Sales
 revenue].DESC));",
 "PatternName":"1Measure_1Dimension_2Filters",
 "Universe":"eFashionS360_EN",
 "Dimension":"State",
 "Measure":"Sales revenue",
 "resultType":"daslResult",
 "currentRank":"0.66",
 "resultopenTime":"1341496011790",
 "resultcloseTime":"1341496013598"
}
{
 "userQuery":"revenue per city",
 "clickedDaslResultQuery":"NonEmpty(([Sales revenue]) IN State::([Sales revenue].DESC));",
 "PatternName":"1Measure_1Dimension_2Filters",
 "Universe":"eFashionS360_EN",
 "Dimension":"State","Measure":"Sales revenue",
 "resultType":"daslResult",
 "currentRank":"0.66",
 "resultopenTime":"1341496014521",
 "resultcloseTime":"1341496016764"
}
\end{lstlisting}

This log keeps trace of the user's query, the pattern that were used, database
entities, the generated structured queries as well as clickthrough data (i.e.
what time and how long results were opened by the user).


\chapter{Mutldimensional queries}
\label{sec:appendix-query}

\section{Automatic generation of SQL/MDX queries}
\label{sec:appendix-query-generation}

We reproduce listing~\ref{lst:query-generation} the automatic SQL generation for
the following query:
\begin{equation}
Q=\left[\begin{array}{lcl}
dimension & = & \{[\textnormal{City}]\}\\
measure & = & \{(\textnormal{Sales revenue})\}\\
filters & = & \emptyset\\
ordering & = & \emptyset\\
truncation & = & \emptyset
\end{array}
\right]
\end{equation}
The datasource is a relational database, and for that reason the query
generation ends up to an SQL query.
\begin{lstlisting}[captionpos=b, caption=SQL query generation (1),
label=lst:query-generation, basicstyle=\small,
   numbers=left,
   breaklines=true,
   breakatwhitespace=true,
   numberstyle=\scriptsize]
   SELECT DISTINCT
   	"EFASHION"."OUTLET_LOOKUP"."CITY" AS DASL_1,
   	sum("EFASHION"."SHOP_FACTS"."AMOUNT_SOLD") AS DASL_2 
   FROM 
   	"EFASHION"."OUTLET_LOOKUP" 
   INNER JOIN 
   	"EFASHION"."SHOP_FACTS" 
   ON
   	("EFASHION"."OUTLET_LOOKUP"."SHOP_ID"="EFASHION"."SHOP_FACTS"."SHOP_ID")
   GROUP BY "EFASHION"."OUTLET_LOOKUP"."CITY"
\end{lstlisting}

The following query:
\begin{equation}
Q=\left[\begin{array}{lcl}
dimension & = & \{[\textnormal{Year}]\}\\
measure & = & \{(\textnormal{Margin})\}\\
filters & = & \{State='Texas'\}\cup\{State='New York'\}\\
ordering & = & \{(Year, (Margin).DESC)\}\\
truncation & = & \emptyset
\end{array}
\right]
\end{equation}
ends up into the following technical query:
\begin{lstlisting}[captionpos=b, caption=SQL query generation (2),
label=lst:query-generation, basicstyle=\small,
   numbers=left,
   breaklines=true,
   breakatwhitespace=true,
   numberstyle=\scriptsize]
SELECT DISTINCT 
	sum("EFASHION"."SHOP_FACTS"."MARGIN") AS DASL_1,
	"EFASHION"."CALENDAR_YEAR_LOOKUP"."YR" AS DASL_2 
FROM
	"EFASHION"."CALENDAR_YEAR_LOOKUP" 
INNER JOIN 
	"EFASHION"."SHOP_FACTS" 
ON (
	"EFASHION"."SHOP_FACTS"."WEEK_ID"
	=
	"EFASHION"."CALENDAR_YEAR_LOOKUP"."WEEK_ID"
) 
INNER JOIN "EFASHION"."OUTLET_LOOKUP" 
ON (
	"EFASHION"."OUTLET_LOOKUP"."SHOP_ID"
	=
	"EFASHION"."SHOP_FACTS"."SHOP_ID"
) 
WHERE
	"EFASHION"."OUTLET_LOOKUP"."STATE" IN ( 'Texas','New York' ) 
GROUP BY
	"EFASHION"."CALENDAR_YEAR_LOOKUP"."YR" 
ORDER BY 1 DESC
\end{lstlisting}





\chapter{Application screenshots}
\label{sec:appendix-screenshots}

\section{Desktop application}
Figure~\ref{fig:appendix-screenshot-desktop} is a screenshot of the desktop
application.
\begin{figure}[h!]
\centering
\includegraphics[width=8cm]{img/desktop-screenshot}
\caption{Screenshot of the desktop application}
\label{fig:appendix-screenshot-desktop}
\end{figure}


\section{iPhone\texttrademark{}/iPad\texttrademark{} application}
Figure~\ref{fig:appendix-screenshot-iphone} is a screenshot of the
iPhone\texttrademark{} application.
\begin{figure}[h!]
\centering
\includegraphics[width=6cm]{img/iphone-screenshot}
\caption{Screenshot of the iPhone\texttrademark{} application}
\label{fig:appendix-screenshot-iphone}
\end{figure}
The component on the top is the search box, where users are invited to type
their queries.
Questions can also be pronounced and recognized (the rounded rectangle entitled
``Search 360'' is indeed a button); in that case a colored bar shows the
amplitude of the voice and let users know that voice recognition service is
running and ready for use.


\section{Search results}
\label{sec:appendix-search-results}
We have introduced section~\ref{sec:personalized-answering-answer-tree}
page~\pageref{sec:personalized-answering-answer-tree} different kinds of
results used in the different applications.
Besides the standard fact table (an example can be found in the section
mentionned above), cross tables can be generated.
\begin{table}[b]
\centering
\begin{tabular}{ccrrr}
& & \multicolumn{3}{c}{\emph{Year}}\\\cline{3-5}
\emph{City} & \emph{Store name} & \multicolumn{1}{c}{\textbf{2009}} &
\multicolumn{1}{c}{\textbf{2010}} &
 \multicolumn{1}{c}{\textbf{2011}}\\\hline \textbf{New York} & \textbf{Magnolia}
 & 1,023,060.70\$ & 1,687,359.10\$ & 1,911,434.30\$ \\\hline \textbf{New York} &
 \textbf{5th} & 644,635.10\$ & 1,076,144.00\$ & 1,239,578.40\$ \\\hline
 \textbf{Miami} & \textbf{Sundance} & 405,985.10\$ & 661,249.80\$ & 811,923.60\$
 \\\hline \textbf{Washington} & \textbf{Tolbooth} & 693,210.50\$ &
 1,215,158.00\$ & 1,053,581.40\$ \\\hline
\end{tabular}
\caption{Example of a cross-table with two hierarchies}
\label{tab:appendix-search-results-cross-table}
\end{table}
Table~\ref{tab:appendix-search-results-cross-table} is an example of
cross-table. The difference with a standard fact table is that it is possible
to have two hierarchies (on both axis, respectively the first hierarchy
projected on the level ``Year'' and the second hierarchy projected on the level
``City'') while there can be only one hierarchy on a classic fact table.

In order to represent an additional hierarchy, the table structure is not
sufficient, and \emph{reports} can be used to render the facts.
\begin{figure}[h]
\centering
\includegraphics[width=8cm]{img/report}
\caption{Example of report with two hierarchies (time and geographic
hierarchies)}
\label{fig:appendix-report}
\end{figure}
On figure~\ref{fig:appendix-report}, we reproduce an example report output for
the query composed of following entities:
\begin{itemize}
  \item measures \textit{Sales revenue} and \textit{Margin}
  \item geographic hierarchy with the dimension \textit{City}
  \item time hierarchy with the dimension \textit{Year}
\end{itemize}

% \chapter{Data sets}
% \label{sec:appendix-data-sets}
% In this section, we present the datasets that have been used for illustrating
% this thesis, and that were used to evaluate the framework.
% 
% \section{\emph{eFashion}, a toy dataset}
% \label{sec:appendix-dataset-efashion}
% \TODO{talk about efashion here}
% 
% \section{Census dataset}
% \TODO{talk about census here}




\chapter{Source code}
\label{sec:appendix-source-code}
We reproduce in this section the main classes that are part of our
implementation.
\begin{lstlisting}[captionpos=b, caption={Search plugin for the pattern
approach}, label=lst:appendix-pattern-search-plugin, basicstyle=\small,
   numbers=left,
   breaklines=true,
   breakatwhitespace=true,
   numberstyle=\scriptsize,language=Java]

public class Pattern2DaslSearchPlugin implements ISearchEnginePlugin {
	
 private static Map<String, DaSlProcessor> daslProcessors = new HashMap<String,
 DaSlProcessor>();

 protected HashMap<String, Object> alreadyAddedQueries;

 @Override
 public ResultIterator search(QueryTree queryTree,
  final SessionContext sessionContext) {
  try {
   IGraph queryGraph = null, 
    featureGraph = null, stfGraph = null, geoGraph = null, 
    timeGraph = null, slGraph = null, repoGraph = null, 
    patternGraph = null, userGraph = null;

   IGraphRepoFactory factory = (IGraphRepoFactory)
   OSGiHelper.getOSGiService(Activator.getContext(), IGraphRepoFactory.class); 
   IGraphRepo graphRepo = factory.getGraphRepo(sessionContext.getUserToken());

   queryGraph = graphRepo.getGraph(QueryTreeVocab.NS_DATA);

   stfGraph = graphRepo.getGraph(STFVocab.NS_DATA);
   featureGraph = graphRepo.getGraph(NlpFeatureVocab.NS_DATA);
   geoGraph = graphRepo.getGraph(GKVocab.NS_GEOGRAPHIC_DATA);
   timeGraph = graphRepo.getGraph(GKVocab.NS_TIME_DATA);
   slGraph = graphRepo.getGraph(SLVocab.NS_DATA);
   repoGraph = graphRepo.getGraph(RepoVocab.NS_UNKNOWN_DATA);
   userGraph = graphRepo.getGraph(STFUserVocab.NS_DATA);
   patternGraph = graphRepo.getGraph(PatternVocab.NS_DATA);
   
   Model joinedModel = ModelFactory.createDefaultModel();
   joinedModel = (Model) queryGraph.getHandler();
   joinedModel = ModelFactory.createUnion(joinedModel, (Model)
    stfGraph.getHandler()); 
   joinedModel = ModelFactory.createUnion(joinedModel,
    (Model) featureGraph.getHandler());
   joinedModel = ModelFactory.createUnion(joinedModel,
    (Model) geoGraph.getHandler());
   joinedModel = ModelFactory.createUnion(joinedModel,
    (Model) timeGraph.getHandler());
   joinedModel = ModelFactory.createUnion(joinedModel,
    (Model) slGraph.getHandler());
   joinedModel = ModelFactory.createUnion(joinedModel,
    (Model) userGraph.getHandler());
   joinedModel = ModelFactory.createUnion(joinedModel,
    (Model) patternGraph.getHandler());
    
   final Model model = joinedModel;
   INodeQuery queryNode = NodeQueryFactory.withType(SLVocab.CLASS_Universe);
   Iterator<INode> universeIterator = slGraph.getNodes(queryNode);
   
   while (universeIterator.hasNext()) {
    INode universeNode = universeIterator.next();
    try {
     // set up connection to universe
     UniverseSessionHelper sessionHelper = new UniverseSessionHelper(
      universeNode.getAttribute(RepoVocab.PROP_DATA_originUri, null)
     );
     DaSlProcessor processor = new DaSlProcessor(sessionHelper,
      universeNode.getLabel());
     
     daslProcessors.put(universeNode.getLabel(), processor);
    } catch (Exception e) {
     logger.error("Could not instantiate dasl processor for "
      + universeNode.getLabel() + " due to "
      + e.getMessage()
     );
    }
   }
   
   final INode bundleNode = stfGraph.createNode(
    STFVocab.CLASS_Search360PlugInSearch
   );
   bundleNode.setLabel("Pattern2Dasl Search Bundle");
   
   final HashMap<String, INode> parameterSettings = new HashMap<String, INode>();
   parameterSettings.put(
    "?queryUri", FakeQueryNodeGenerator.doIt(queryTree, queryGraph)
   );
   
   final PriorityQueue<ScoredResultModel> constructedModels = new PriorityQueue<ScoredResultModel>();
   Thread patternExecutorThread = new Thread() {
    @Override
    public void run() {
     PatternExecutor.applyPatterns(model, constructedModels,
      sessionContext.getUserToken(), parameterSettings, bundleNode
     );
    }
   };
   patternExecutorThread.start();
   
   final PriorityQueue<BusinessQuery> bqueries = new PriorityQueue<BusinessQuery>();
   Thread objectWrapperThread = new Thread() {
    @Override
    public void run() {
     BQueryObjectWrapper.getBQueryObjects(bqueries,constructedModels, model);
    }
   };
   objectWrapperThread.start();
   
   BufferedResultIterator resIt = new BufferedResultIterator(
    this.getClass().getName(), sessionContext
   ) {
    boolean isRunning;
    boolean isQueueDone = false;
    
    int NTHREADS = evalConfiguration.getProperty("EVAL_MODE").toBoolean() 
     ? 1 : Runtime.getRuntime().availableProcessors() * 2;
    final ExecutorService exec = Executors.newFixedThreadPool(NTHREADS);
    final Queue<Result> res = new LinkedBlockingQueue<Result>();
    Map<String, DaslResult> alreadyAddedQueries = new HashMap<String, DaslResult>();
    IGraphRepoFactory factory = (IGraphRepoFactory) OSGiHelper
     .getOSGiService(Activator.getContext(),IGraphRepoFactory.class);
    
    IGraphRepo graphRepo = factory.getGraphRepo(sessionContext.getUserToken());
    IGraph slGraph = graphRepo.getGraph(SLVocab.NS_DATA);
    
    public void run() throws Exception {
     Thread schedulerThread = new Thread() {
      @Override
      public void run() {
       while (!isQueueDone) {
        while (bqueries == null || bqueries.peek() == null) {
         try {
          Thread.sleep(50);
         } catch (InterruptedException e) {
         }
        }
        while (bqueries.peek() != null) {
         BusinessQuery businessQuery = bqueries.poll();
         if (businessQuery.getDatasource().equals("$SIGNAL_DONE$")) {
          isQueueDone = true;
          break;
         }
         DaslResult daslQueryAndChartType;
         try {
          daslQueryAndChartType = BQueryTranslation.bQueryToDaslQuery(
           businessQuery, sessionContext.getUserToken(), slGraph, true
          );
          if (alreadyAddedQueries.containsKey(
           daslQueryAndChartType.getDaslQuery()	
           + daslQueryAndChartType.getUniverse())
          ) {
           DaslResult updatedDaslResult = alreadyAddedQueries
            .get(daslQueryAndChartType.getDaslQuery()
            + daslQueryAndChartType.getUniverse());
           if (daslQueryAndChartType.getScore() > updatedDaslResult.getScore()) {
            updatedDaslResult.setScore(daslQueryAndChartType.getScore());
            updatedDaslResult.setPatternName(
             daslQueryAndChartType.getPatternName()
            );
           }
           continue;
          }
          scheduleQueryForExecution(daslQueryAndChartType);
         } catch (Exception e) {
          logger.error(e.getMessage(), e);
         }
        }
       }
       exec.shutdown();
      }
     };
     schedulerThread.start();
    }
    
    private void scheduleQueryForExecution(
     final DaslResult daslResult) {
      alreadyAddedQueries.put(
       daslResult.getDaslQuery() + daslResult.getUniverse(), daslResult
      );
      
      try {
       logger.debug("executing query="
        + daslResult.getDaslQuery() + " with score "
        + daslResult.getScore()
       );
       Runnable requestHandler = new Runnable() {
        public void run() {
         try {
          daslProcessors.get(daslResult.getUniverse()).processQuery(daslResult);
          res.offer(daslResult);
         } catch (UnsupportedOperationException e) {
          logger.debug("query " + daslResult.getDaslQuery() 
           + " encountered an error"
          ); 
         } catch (Exception e) {
          logger.error(
           "dasl encountered an error trying to execute Query "
           + daslResult.getDaslQuery() + "in universe " + daslResult.getUniverse()
           + " from pattern " + daslResult.getPatternName(), e
          );
         }
        }
       };
       exec.execute(requestHandler);
       
      } catch (Exception e) {
       logger.error("query=" + daslResult.getDaslQuery() + " failed", e);
      }
     }
     
     @Override
     public void remove() {
      exec.shutdownNow();
     }
     
     @Override
     public Map<String, Object> getStatistics() {
      return null;
     }
     
     @Override
     protected List<Result> moreResults(Session session) {
      if (isRunning == false) {
       isRunning = true;
       try {
        run();
       } catch (Exception e) {
        logger.error(e);
       }
      }
      while (res.peek() == null && !hasFinishedExecution()) {
       try {
        Thread.sleep(50);
       } catch (InterruptedException e) {
      }
     }
     
     List<Result> intermResult = new ArrayList<Result>();
     while (res.peek() != null) {
      intermResult.add(res.poll());
     }
     return intermResult;
    }
    
    private boolean hasFinishedExecution() {
     return exec.isTerminated() && res.peek() == null;
    }
    
    @Override
    protected boolean hasMoreResults() {
     if (isRunning == false) {
      isRunning = true;
      try {
       run();
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
     boolean finished = hasFinishedExecution();
     return !finished;
    }
   };
   
   // trigger run method
   resIt.hasNext();
   return resIt;
   
  } catch (Exception e) {
   logger.error("", e);
  }
  
  return new ListResultIterator(
   this.getClass().getName(), sessionContext, new ArrayList<Result>());
  }
  
  public static void populatePatternGraph(
   final IGraphRepo repo, final Model model, final INode bundleNode, 
   final IGraph slGraph, final IGraph repoGraph, final String queryLabel
  ) {
   final IGraph patternGraph = repo.getGraph(PatternVocab.NS_DATA);
   Thread populater = new Thread() {
    @Override
    public void run() {
     String query = ""
      + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n "
      + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n "
      + "SELECT ?query ?patternLabel ?bquery ?entityUri ?universeName\n "
      + "WHERE { "
      + "?pattern rdf:type <urn:grepo/pattern#Pattern> . "
      + "?pattern rdfs:label ?patternLabel . "
      + "?pattern <urn:grepo/pattern#matches> ?query . "
      + "?query rdf:type <urn:grepo/pattern#Query> . "
      + "?query <urn:grepo/pattern#hasBusinessQuery> ?bquery . "
      + "?bquery rdf:type <http://research.sap.corp/pattern/bquery> . "
      + "?bquery <http://research.sap.corp/pattern#referencesEntity> ?entity . "
      + "?entity rdfs:isDefinedBy ?entityUri . "
      + "?bquery <http://research.sap.corp/pattern/bquery/dataSource> ?universeName . "
      + "}";
     
     Query q = QueryFactory.create(query);
     QueryExecution qEx = QueryExecutionFactory.create(q, model);
     ResultSet rs = qEx.execSelect();
     
     int bQueryCount = 0;
     while (rs.hasNext()) {
      QuerySolution sol = rs.next();
      // patternnode
      String patternUri = PatternVocab.NS_DATA + "/"
       + URLEncoder.encode(sol.getLiteral("patternLabel").toString());
      INode patternNode = patternGraph.getNode(patternUri);
      INode queryNode = patternGraph.createNode(PatternVocab.CLASS_Query);
      queryNode.setLabel(queryLabel);
      patternGraph.createStatement(
       patternNode,PatternVocab.PRED_Pattern_matches, queryNode, bundleNode
      );
      
      // bquery
      String bqueryUri = PatternVocab.NS_DATA + "/"
       + URLEncoder.encode(sol.get("bquery").toString()
      );
      INode bqueryNode = patternGraph.getNode(bqueryUri);
      
      if (bqueryNode == null) {
       bqueryNode = patternGraph.createNode(
        bqueryUri, PatternVocab.CLASS_BusinessQuery
       );
       bqueryNode.setLabel("bquery " + bQueryCount++); 
       patternGraph.createStatement(
        patternNode, PatternVocab.PRED_Pattern_hasBusinessQuery,
        bqueryNode, bundleNode
       );
      }
      
      INode entityNode = slGraph.getNode(sol.get("entityUri").toString());
      patternGraph.createStatement(
       bqueryNode,PatternVocab.PRED_BQuery_referencesEntity, 
       entityNode, bundleNode
      );
     }
    }
   };
   populater.start();
  }
 }
\end{lstlisting}







